#include "Objects/BaseObject.hpp"

#include "ServerEntityManager.hpp"

ServerEntityManager::ServerEntityManager():EntityManager(){
	size = 1024;
    entities = new Entity*[1024];

	for(unsigned short i = 0; i < size; i++){
		entities[i] = 0;
	}
    Character registerent;
	registerObject(&registerent);
	Player registerp;
	registerObject(&registerp);
    
}

void ServerEntityManager::init(){
	EntityManager::init("Objects/s_entities.lua");
}

Entity* ServerEntityManager::createEntity(const char* name){

	for(unsigned short i = 0; i < size; i++){
		if(!entities[i]){
			entities[i] = new Character();
            entities[i]->init(name, i);
			((Character*)entities[i])->init(map, 0, 0, 0);

            runStartup(entities[i], name);
			
			return entities[i];
		}
	}
	return 0;
}

void ServerEntityManager::update(unsigned int frameTime){
	for(unsigned short i = 0; i < size; i++){
		if(entities[i]){
            //Entity has been marked for destruction
            if(entities[i]->destroy){
                destroyEntity(entities[i]);
                continue;
            }

			byte dir = entities[i]->direction;

			runUpdate(entities[i]);

            entities[i]->move();
			
			if(dir != entities[i]->direction){
				Packet_ServerEntityLocation entityLocation = PacketHelper::ServerEntityLocation(entities[i]);
				NetworkHandler::getInstance()->sendAllMessageInArea(
                    Message::m_s_EntityMove, &entityLocation, entityLocation.x, entityLocation.y);
			}
		}
	}
}

bool ServerEntityManager::destroyEntity(Entity* ent){
	if(entities[ent->index] == ent){
        if(ent->destroy == BaseObject::d_Clean){
            ent->destroy = BaseObject::d_Destroy;
        }else if(ent->destroy == BaseObject::d_Destroy){
            runDestroy(entities[ent->index]);
            NetworkHandler::getInstance()->sendAllMessage(Message::m_s_DestroyEntity, &ent->index);
            //Mark for deletion on next update.
            entities[ent->index]->destroy = BaseObject::d_Delete;
        }else if(ent->destroy == BaseObject::d_Delete){
            uint16_t index = ent->index;
            delete entities[index];
            entities[index] = 0;
        }
        return true;
	}
    return false;
}

Entity* ServerEntityManager::getEntity(uint16_t index){
	return entities[index];
}

void ServerEntityManager::bind(lua_State* luaState){

	luabind::module(luaState)[
        luabind::class_<ServerEntityManager>("EntityManager")
			.def_readonly("size", &ServerEntityManager::size)
			.def("getEntity", &ServerEntityManager::getEntity)
			.def("destroyEntity", &ServerEntityManager::destroyEntity)
    ];
}

void ServerEntityManager::push(lua_State* luaState){
	luabind::object o = luabind::object(luaState, this);
    o.push(luaState);
}